using Engine;
using Engine.Graphics;
using Game;
using GameEntitySystem;

namespace SCIENEW {
    public class SteamTurbineDevice : IlluminableModelDevice, IEntityDevice<ComponentSteamTurbine>, IFluidTransferrerDevice {

        public BlockMesh m_fanMesh = new();
        public BlockMesh m_displayFanMesh = new();

        public SteamTurbineDevice() : base("SteamTurbineDevice", "Models/SteamTurbine", "SteamTurbine", "SteamTurbine_Working") {
            Model model = ContentManager.Get<Model>("Models/SteamTurbine");
            Matrix boneAbsoluteTransform = BlockMesh.GetBoneAbsoluteTransform(model.FindMesh("Fan").ParentBone);
            m_fanMesh.AppendModelMeshPart(
                model.FindMesh("Fan").MeshParts[0],
                boneAbsoluteTransform * Matrix.CreateTranslation(0.5f, 0f, 0.5f),
                makeEmissive: false,
                flipWindingOrder: false,
                doubleSided: true,
                flipNormals: false,
                Color.White
            );
            m_displayFanMesh.AppendModelMeshPart(
                model.FindMesh("Fan").MeshParts[0],
                boneAbsoluteTransform * Matrix.CreateTranslation(0, -0.5f, 0f),
                makeEmissive: false,
                flipWindingOrder: false,
                doubleSided: true,
                flipNormals: false,
                Color.White
            );
        }

        public override void DrawBlock(PrimitivesRenderer3D primitivesRenderer, int value, Color color, float size, ref Matrix matrix, DrawBlockEnvironmentData environmentData) {
            BlocksManager.DrawMeshBlock(
                primitivesRenderer,
                m_standaloneBlockMesh,
                IndustrialModLoader.IETexture,
                color,
                size,
                ref matrix,
                environmentData
            );
            BlocksManager.DrawMeshBlock(
                primitivesRenderer,
                m_displayFanMesh,
                IndustrialModLoader.IETexture,
                color,
                size,
                ref matrix,
                environmentData
            );
        }

        public override void GenerateTerrainVertices(BlockGeometryGenerator generator, TerrainGeometry geometry, int value, int x, int y, int z) {
            generator.GenerateShadedMeshVertices(
                BlocksManager.Blocks[BaseDeviceBlock.Index],
                x,
                y,
                z,
                IsLight(value) ? m_litBlockMeshesByData[GetDirection(value)] : m_blockMeshesByData[GetDirection(value)],
                Color.White,
                null,
                null,
                geometry.GetGeometry(IndustrialModLoader.IETexture).SubsetAlphaTest
            );
            if (!IsLight(value)) {
                generator.GenerateShadedMeshVertices(
                    BlocksManager.Blocks[BaseDeviceBlock.Index],
                    x,
                    y,
                    z,
                    m_fanMesh,
                    Color.White,
                    null,
                    null,
                    geometry.GetGeometry(IndustrialModLoader.IETexture).SubsetAlphaTest
                );
            }
        }

        public string GetEntityName(int value) => "SteamTurbine";

        public Widget GetWidget(IInventory inventory, ComponentSteamTurbine component) => new SteamTurbineWidget(inventory, component);

        public override DeviceBehavior[] GetBehaviors(Project project) => [new SteamTurbineDeviceBehavior(project), new FluidTransferrerDeviceBehavior(project)];

        public FluidTransferrer? CreateFluidTransferrer(SubsystemFluidTransfer subsystemFluidTransfer, SubsystemTerrain subsystemTerrain, int value, Point3 point) => new SteamTurbineTransferrer(point, subsystemTerrain);

        public FluidConnector? GetConnector(SubsystemTerrain terrain, int value, int face, int x, int y, int z) {//侧面，背面为流体输入口
            int deviceDirection = GetDirection(value);
            DevicesUtils.GetSideFaceOfXZ(deviceDirection, out int sideFace1, out int sideFace2);
            int backFace = CellFace.OppositeFace(deviceDirection);
            if (face == backFace
                || face == sideFace2
                || face == sideFace1
                || face == 5)
                return new FluidConnector(new CellFace(x, y, z, face), FluidConnectorType.Input, 16);
            return null;
        }
    }
}